import flash.display.Sprite;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Shape;
import flash.events.Event;
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.geom.Matrix;
import flash.utils.Timer;

import haxe.FastList;
import haxe.Timer;

import nme.Assets;
import TileModel;
import HealthBarView;
import BaseLevel;
import Kongregate;

import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import flash.text.TextFormat;
import flash.text.TextFormatAlign;

class CollisionArrayLevel extends BaseLevel
{
  
  private var _pinkMap:Array<Array<Int>>;  
  private static inline var MAX_TILE_SIZE:Int = 64;
  private static inline var MAP_COLUMNS:Int = 19;
  private static inline var MAP_ROWS:Int = 8;
  
  //tile ID s in tile sheet
  private static inline var BOX:Int = 00;
  private static inline var SKY:Int = 10;
  private static inline var PLATFORM:Int = 11;
  private static inline var MACHINE_GUN:Int = 01;
  private static inline var PISTOL:Int = 02;
  private static inline var SHOTGUN:Int = 03;
  private static inline var DOOR:Int = 13;

  private static inline var PINK:Int = 21;
  private static inline var BLUE:Int = 20;

  private static inline var PinkRadius:Float = 20.5;
  private static inline var BlueRadius:Float = 20.5;
  public var _CircleModel:CircleModel;
  public var _CircleView:PlayerCircleView;
  public var _CircleController:CircleController;
  public var _c1:CircleModel;
  public var _c1_View:CircleView;
  public var _c2:CircleModel;
  public var _c2_View:CircleView;
  public var _c3:CircleModel;
  public var _c3_View:CircleView;
  public var _c4:CircleModel;
  public var _c4_View:CircleView;
  public var _c5:CircleModel;
  public var _c5_View:CircleView;
  public var _VectorModel:VectorModel;
  public var _VectorView:VectorView;
  private var _SpriteLayer:Sprite;
  public var  WelcomeText:TextField;
  public var  ExplationText:TextField;
  public var  ExplationText2:TextField;
  public var  ForumlaText:TextField;
  public var  ForumlaText2:TextField;
  public var  CircleSizeText:TextField;
  private var _collisionCircleMap:Array<Array<List<CircleMV>>>;
  public function new(stage:Dynamic){
  super(stage);
  MAP_COLUMNS = 32;
    removeChild(_staticBackgroundBitmap);
    removeChild(_backgroundBitmap);
    removeChild(_foregroundBitmap);
  _staticBackgroundBitmapData = Assets.getBitmapData("Cardboard_Background.png");
  _staticBackgroundBitmap = new Bitmap(_staticBackgroundBitmapData);

  _backgroundBitmapData = new BitmapData(MAP_COLUMNS * MAX_TILE_SIZE, 
          MAP_ROWS * MAX_TILE_SIZE, true, 0);
  _backgroundBitmap = new Bitmap(_backgroundBitmapData);

  _foregroundBitmapData = new BitmapData(MAP_COLUMNS * MAX_TILE_SIZE, 
          MAP_ROWS * MAX_TILE_SIZE, true, 0);
  _foregroundBitmap = new Bitmap(_foregroundBitmapData);

  _SpriteLayer = new Sprite();
  _SpriteLayer.graphics.beginFill(0x0000000,0);
  _SpriteLayer.graphics.drawRect(0,0,MAP_COLUMNS * MAX_TILE_SIZE,MAP_ROWS * MAX_TILE_SIZE);
  _SpriteLayer.visible = true;

  _camera = new Rectangle (0, 0, stage.stageWidth, stage.stageHeight);

    addChild(_staticBackgroundBitmap);
    addChild(_backgroundBitmap);
    addChild(_foregroundBitmap);
    addChild(_SpriteLayer);
  _platformMap = 
	[
		  [PLATFORM,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,PLATFORM,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,PLATFORM],
		  [PLATFORM,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,PLATFORM,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,PLATFORM],
		  [PLATFORM,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,PLATFORM,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,PLATFORM],
		  [PLATFORM,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,PLATFORM,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,PLATFORM],
		  [PLATFORM,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,PLATFORM,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,PLATFORM],
		  [PLATFORM,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,PLATFORM,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,PLATFORM],
		  [PLATFORM,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,PLATFORM,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,SKY,PLATFORM],
		  [PLATFORM,PLATFORM,PLATFORM,PLATFORM,PLATFORM,PLATFORM,PLATFORM,PLATFORM,PLATFORM,PLATFORM,PLATFORM,PLATFORM,PLATFORM,PLATFORM,PLATFORM,PLATFORM,PLATFORM,PLATFORM,PLATFORM,PLATFORM,PLATFORM,PLATFORM,PLATFORM,PLATFORM,PLATFORM,PLATFORM,PLATFORM,PLATFORM,PLATFORM,PLATFORM,PLATFORM,PLATFORM,PLATFORM,PLATFORM,PLATFORM,PLATFORM,PLATFORM,PLATFORM,PLATFORM,PLATFORM,PLATFORM,PLATFORM]
	];
  _gameObjectMap = 
	[
	    [-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
	    [-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
	    [-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
	    [-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
	    [-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
	    [-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
	    [-1,DOOR,BOX,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,DOOR,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
	    [-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
	  ]  ;


  buildReserveEnemies();


  // myTimer = new Timer(12);
  //   myTimer.addEventListener("timer", OnEnter);
  //   myTimer.start();
  //Add the game bitmaps
			  
			  //Run the buildMap method to convert the
			  //map array data into a visual display
			  

      
    ExplationText = new TextField();
    ExplationText.htmlText = "<font size ='16'>When you start Making a large game, you don't want to check against every object, every frame. That's were collision arrays come in.</font>";
    ExplationText.background = true;
    ExplationText.backgroundColor = 0xFFFFFF;
    ExplationText.x = 64;ExplationText.y = 0;
    ExplationText.width = 192; ExplationText.height = 120;
    ExplationText.wordWrap = true;
    ExplationText.border = true;
    _SpriteLayer.addChild(ExplationText);

    ExplationText2 = new TextField();
    ExplationText2.htmlText = "<font size ='16'>If all your objects are less than a certain square size (i.e. 64x64).  Then you can divide the stage into squares and assign each object to the closet square.  Then You merely need to check the 9 squares around an object(usually the main character) for  colliding objects.<font>";
    ExplationText2.background = true;
    ExplationText2.backgroundColor = 0xFFFFFF;
    ExplationText2.x = 276;ExplationText2.y = 25;
    ExplationText2.width = 256; ExplationText2.height = 164;
    ExplationText2.wordWrap = true;
    ExplationText2.border = true;
    _SpriteLayer.addChild(ExplationText2);

    ForumlaText = new TextField();
    ForumlaText.width = 400; ForumlaText.height = 320;
    ForumlaText.htmlText = "<font size ='16'>//build Map
    _collisionCircleMap = [[]];
    for(row in 0...MAP_ROWS)
    {
      _collisionCircleMap[row] = [];
      for(column in 0...MAP_COLUMNS)	
      {
	_collisionCircleMap[row][column] = new ListOfCellCircles();
      }
    }
   for(circle in ListOfAllCircles)
   {
     _collisionCircleMap[circle.row][circle.column].add(circle);
   }</font>";
    ForumlaText.x = 600;ForumlaText.y = 5;

    ForumlaText.wordWrap = true;
    ForumlaText.border = true;
ForumlaText.background =true;
ForumlaText.backgroundColor = 0xFFFFFF;
    _SpriteLayer.addChild(ForumlaText);



   ForumlaText2 = new TextField();
    ForumlaText2.width = 400; ForumlaText2.height = 384;
    ForumlaText2.htmlText = "<font size ='16'>//check squares
	for(column in -1...2)
	{
	  for(row in -1...2)
	  {
	    if(_s1.mapRow + row &lt; MAP_ROWS &&
	       _s1.mapRow + row &gt;= 0 &&
	       _s1.mapColumn + column &lt; MAP_COLUMNS &&
	       _s1.mapColumn + column &gt;= 0)
	    {
	      for(model in _collisionCircleMap[_s1.mapRow + row][_s1.mapColumn + column])
	      {
		//check Collision
	      }
	    }
	  }
	}</font>";
    ForumlaText2.x = 1000;ForumlaText2.y = 5;

    ForumlaText2.wordWrap = true;
    ForumlaText2.border = true;
ForumlaText2.background =true;
ForumlaText2.backgroundColor = 0xFFFFFF;
    _SpriteLayer.addChild(ForumlaText2);


    CircleSizeText = new TextField();
    CircleSizeText.width = 150; CircleSizeText.height = 180;
    CircleSizeText.htmlText = "<font size ='16'>Make sure they objects are less than a section in the grid, otherwise collisions can occur before you check for them.</font>";
    CircleSizeText.x = 1456;CircleSizeText.y = 50;
    CircleSizeText.background = true;
    CircleSizeText.backgroundColor = 0xFFFFFF;
    CircleSizeText.wordWrap = true;
    CircleSizeText.border = true;
    _SpriteLayer.addChild(CircleSizeText);

    _c1 = new CircleModel("Secondary");
    _c1_View = new CircleView(_c1);
    _SpriteLayer.addChild(_c1_View);
    _c1.setX = 288;_c1.yPos = 416;

    _c2 = new CircleModel("Secondary",60);
    _c2_View = new CircleView(_c2);
    _SpriteLayer.addChild(_c2_View);
    _c2.setX = 1534;_c2.yPos = 275;

    _c3 = new CircleModel("Secondary",30);
    _c3_View = new CircleView(_c3);
    _SpriteLayer.addChild(_c3_View);
    _c3.setX = 1664;_c3.yPos = 320;

    _c4 = new CircleModel("Secondary",30);
    _c4_View = new CircleView(_c4);
    _SpriteLayer.addChild(_c4_View);
    _c4.setX = 1792;_c4.yPos = 352;

    _c5 = new CircleModel("Secondary",30);
    _c5_View = new CircleView(_c5);
    _SpriteLayer.addChild(_c5_View);
    _c5.setX = 1822;_c5.yPos = 342;

    _collisionCircleMap = [[]];
    for(row in 0...MAP_ROWS)
    {
      _collisionCircleMap[row] = [];
      for(column in 0...MAP_COLUMNS)	
      {
	_collisionCircleMap[row][column] = new List<CircleMV>();
      }
    }

    //Add circles
    _collisionCircleMap[_c1.mapRow][_c1.mapColumn].add(new CircleMV(_c1,_c1_View));    
    _collisionCircleMap[_c2.mapRow][_c2.mapColumn].add(new CircleMV(_c2,_c2_View));  
    _collisionCircleMap[_c3.mapRow][_c3.mapColumn].add(new CircleMV(_c3,_c3_View));  
    _collisionCircleMap[_c4.mapRow][_c4.mapColumn].add(new CircleMV(_c4,_c4_View));  
    _collisionCircleMap[_c5.mapRow][_c5.mapColumn].add(new CircleMV(_c5,_c5_View));  


    }
public override function Load(inVolume:Bool,inSound:Bool,inKongVar:CKongregate,inDifficulty:Int)
{
 super.Load(inVolume,inSound,inKongVar,inDifficulty);
 _backgroundBitmapData.fillRect(_backgroundBitmapData.rect, 0);
 buildMap(_platformMap);
 buildMap(_gameObjectMap);


    for(mapColumn in 0...MAP_COLUMNS)
    {
      for(mapRow in 0...MAP_ROWS)
      {
	var grid:TileModel 
	  = new TileModel
	  (
	    64,
		1, 2, 
	      mapRow, mapColumn, 
	      MAX_TILE_SIZE, MAX_TILE_SIZE
	  );
	    drawGameObject(grid, _backgroundBitmapData);
	  for(mv in _collisionCircleMap[mapRow][mapColumn])
	  {

	    var shape = new Shape();
	  shape.graphics.beginFill(0x0000FF,0.2);
	  shape.graphics.drawRect((mapColumn)*MAX_TILE_SIZE,(mapRow)*MAX_TILE_SIZE,MAX_TILE_SIZE,MAX_TILE_SIZE);
	  _backgroundBitmapData.draw(shape);
	    
	  }
      }
    }
  
}

public override function checkWin():Bool
{
  if(!_boxModel.exit)
    {return false;}
  _boxModel.exit = false;
  var Door1 = new SquareModel();
  Door1.xPos = 1*64;
  Door1.yPos = 6*64;
  Door1.width = 64;
  Door1.height = 64;
  var boxSquare = new SquareModel();
  boxSquare.xPos = _boxModel.xPos-_boxModel.width;
  boxSquare.yPos = _boxModel.yPos-_boxModel.height;
  boxSquare.width = _boxModel.width;
  boxSquare.height = _boxModel.height;
  if(_collisionController.squareModelCollision(Door1,boxSquare))
  {
    return true;
  }
    var Door2 = new SquareModel();
  Door2.xPos = 23*64;
  Door2.yPos = 6*64;
  Door2.width = 64;
  Door2.height = 64;
  if(_collisionController.squareModelCollision(Door2,boxSquare))
  {
    return true;
  }
  return  false;
}

  public  override function UnLoad()
  {

      super.UnLoad();
      //_MainCharacterController = null;

  }
public function checkCollisionCircle(_c1:CircleModel,_c2:CircleModel,totalRadii:Float,view:CircleView)
{
	var m = Math.sqrt(Math.pow(_c1.xPos -_c2.xPos,2) +
		  Math.pow( _c1.yPos - _c2.yPos,2));   
	if(m < totalRadii)
	{
	  view.hit();
	}
	else
	{
	  view.unHit();
	}
}
override function OnEnter(e:flash.events.Event)
{
    try
    {
      super.OnEnter(e);
      
 
      _SpriteLayer.scrollRect = _camera;

_c2_View.unHit();
	for(column in -1...2)
	{
	  for(row in -1...2)
	  {
	    if(_boxModel.mapRow + row < MAP_ROWS &&
	       _boxModel.mapRow + row >= 0 &&
	       _boxModel.mapColumn + column < MAP_COLUMNS &&
	       _boxModel.mapColumn + column >= 0)
	    {	
	      var boxSquare = new SquareModel();
	      boxSquare.xPos = _boxModel.xPos;
	      boxSquare.yPos = _boxModel.yPos;
	      boxSquare.width = _boxModel.width;
	      boxSquare.height = _boxModel.height;
	      var shape = new Shape();
	      shape.graphics.beginFill(0xFF0000,0.2);
	      shape.graphics.drawRect((_boxModel.mapColumn + column)*MAX_TILE_SIZE,(_boxModel.mapRow + row)*MAX_TILE_SIZE,MAX_TILE_SIZE,MAX_TILE_SIZE);
	      _foregroundBitmapData.draw(shape);
	      for(mv in _collisionCircleMap[_boxModel.mapRow + row][_boxModel.mapColumn + column])
	      {
		if(checkCollisionCircleSquare(mv.model,boxSquare))
		{
		  mv.view.hit();
		}
		else
		{
		  mv.view.unHit();
		}
	      }
	    }

	  }
	}

      //_gunView.scrollRect = _camera;
      //drawGunObject(_gunModel,_currentGunBitmapData, _foregroundBitmapData); 
    }
catch(err:Dynamic)
    {
    trace(err.message);
    }
}

public function checkCollisionCircleSquare(_c1:CircleModel,_s1:SquareModel)
{
  var region = DetermineSpot(_c1,_s1);
  var collision = false;
      if(region == "topMiddle"
      || region == "bottomMiddle"
      || region == "leftMiddle"
      || region == "rightMiddle")
      {
	collision = SquareCollisionPart(_c1,_s1);
      }
      else
      {
	var cornerV0 = GetCornerCollisionPart(_c1,_s1,region);
	if(cornerV0.m < _c1.radius)
	{
	  collision = true;
	}
      }
  return collision;
}
public function SquareCollisionPart(_c1:CircleModel,_s1:SquareModel):Bool
{
      var _v0:VectorModel = new VectorModel(_c1.xPos,_c1.yPos, _s1.xPos+_s1.width/2,_s1.yPos+_s1.height/2);
      var collision = false;
      if(Math.abs(_v0.vx) < _c1.radius + _s1.width * 0.5)
      {
	if(Math.abs(_v0.vy) < _c1.radius + _s1.height * 0.5)
	{
	  collision = true;
	}
      }
      return collision;
}
public function GetCornerCollisionPart(_c1:CircleModel,_s1:SquareModel,region:String):VectorModel
{
    var cornerV0 :VectorModel = new VectorModel();
    if(region == "topLeft")
    {
     cornerV0 = new VectorModel
	(
	_c1.xPos,
	_c1.yPos,
	_s1.xPos,
	_s1.yPos
	);
    }
    else if(region == "topRight")
    {
      cornerV0 = new VectorModel
	(
	_c1.xPos,
	_c1.yPos,
	_s1.xPos + _s1.width,
	_s1.yPos
	);

    }
    else if(region == "bottomLeft")
    {
      cornerV0 = new VectorModel
	(
	_c1.xPos,
	_c1.yPos,
	_s1.xPos,
	_s1.yPos +_s1.height
	);
    }
    else if(region == "bottomRight")
    {
      cornerV0 = new VectorModel
	(
	_c1.xPos,
	_c1.yPos,
	_s1.xPos +_s1.width,
	_s1.yPos +_s1.height
	);
    }
    return cornerV0;
}

public function DetermineSpot(_c1:CircleModel,_s1:SquareModel):String
{
    var region:String = "";
    //Is the circle above the rectangle's top edge?
    if(_c1.yPos < _s1.yPos)
    {
      //If it is, we need to check whether it's in the 
      //top left, top center or top right
      if(_c1.xPos < _s1.xPos)
      {
	region = "topLeft";
      }
      else if (_c1.xPos > _s1.xPos + _s1.width)
      {
	region = "topRight";
      }
      else
      {
	region = "topMiddle";
      }
    }
    //below the bottom edge?
    else if (_c1.yPos > _s1.yPos + _s1.height)
    {
      //If it is, we need to check whether it's in the 
      //bottom left, bottom center or bottom right
      if(_c1.xPos < _s1.xPos)
      {
	region = "bottomLeft";
      }
      else if (_c1.xPos > _s1.xPos + _s1.width )
      {
	region = "bottomRight";
      }
      else
      {
	region = "bottomMiddle";
      }
    }
    // the left or right side?
    else
    {
      if(_c1.xPos < _s1.xPos )
      {
	region = "leftMiddle";
      }
      else
      {
	region = "rightMiddle";
      }
    }
    return region;
}

  public override function buildReserveEnemies()
  {
  }
}